package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.CommonCodeMsg;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mapper.OrderInfoMapper;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.web.feign.ProductFeignApi;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by lanxw
 */
@Service
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private ProductFeignApi productFeignApi;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    public List<SeckillProductVo> queryByTime(Integer time) {
        List<SeckillProductVo> seckillProductVoList = new ArrayList<>();
        //1.查询当天商品的数据，根据指定场次进行获取，获取秒杀商品集合
        List<SeckillProduct> seckillProducts = seckillProductMapper.queryCurrentlySeckillProduct(time);
        if (seckillProducts.size()==0) {
            return seckillProductVoList;
        }
        //2.遍历秒杀商品的集合，获取商品ID集合
        List<Long> productIdList = new ArrayList<>();
        for(SeckillProduct seckillProduct:seckillProducts){
            productIdList.add(seckillProduct.getProductId());
        }
        Result<List<Product>> result = productFeignApi.queryByIds(productIdList);
        if (result==null||result.hasError()) {
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        //3.进行远程调用，将商品ID集合作为参数，获取商品集合数据
        List<Product> productList = result.getData(); //TODO
        //将List转成Map
        Map<Long,Product> productMap = new HashMap<>();
        for(Product product:productList){
            productMap.put(product.getId(),product);
        }
        //4.将商品数据和秒杀商品数据进行聚合.封装成vo对象进行返回.
        for(SeckillProduct seckillProduct:seckillProducts){
            //获取秒杀商品所对应的商品ID
            Long productId = seckillProduct.getProductId();
            //获取对应的商品对象
            Product product = productMap.get(productId);
            SeckillProductVo vo = new SeckillProductVo();
            //把product数据设置的vo中
            BeanUtils.copyProperties(product,vo);
            //把seckillProduct的数据设置到vo中
            BeanUtils.copyProperties(seckillProduct,vo);
            seckillProductVoList.add(vo);
        }
        return seckillProductVoList;
    }

    @Override
    public SeckillProductVo find(Integer time, Long seckillId) {
        SeckillProduct seckillProduct=seckillProductMapper.find(seckillId);
        if (seckillProduct==null) {
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
       List<Long> ids = new ArrayList<>();
        ids.add(seckillProduct.getProductId());
        Result<List<Product>> result = productFeignApi.queryByIds(ids);
        if (result==null||result.hasError()) {
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        Product product = result.getData().get(0);
        SeckillProductVo vo = new SeckillProductVo();
        BeanUtils.copyProperties(product,vo);
        BeanUtils.copyProperties(seckillProduct,vo);
        vo.setCurrentCount(seckillProduct.getStockCount());
        return vo;
    }
//   @Transactional
//    @Override
//    public String doSeckill(Integer time, Long seckillId, String phone) {
//        seckillProductService.decrStockCount(seckillId);
//        String orderNo=createOrder(time,seckillId,phone);
//        return orderNo;
//    }
//
//    private String createOrder(Integer time, Long seckillId, String phone) {
//        OrderInfo orderInfo = new OrderInfo();
//        SeckillProductVo vo = seckillProductService.find(time, seckillId);
//        orderInfo.setIntegral(vo.getIntegral());
//        orderInfo.setProductId(vo.getProductId());
//        orderInfo.setProductImg(vo.getProductImg());
//        orderInfo.setProductName(vo.getProductName());
//        orderInfo.setProductPrice(vo.getProductPrice());
//        orderInfo.setSeckillDate(vo.getStartDate());
//        orderInfo.setSeckillId(vo.getId());
//        orderInfo.setSeckillTime(vo.getTime());
//        orderInfo.setSeckillPrice(vo.getSeckillPrice());
//        orderInfo.setUserId(Long.parseLong(phone));
//        orderInfo.setCreateDate(new Date());
//        orderInfo.setOrderNo(String.valueOf(IdGenerateUtil.get().nextId()));
//        orderInfoMapper.insert(orderInfo);
//        return orderInfo.getOrderNo();
//    }

    @Override
    public int decrStockCount(Long seckillId) {
     return    seckillProductMapper.decrStock(seckillId);
    }

    @Override
    public List<SeckillProductVo> queryByTimeFromCache(Integer time) {
        String seckillProductCacheKey = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(String.valueOf(time));
        List<Object> values = redisTemplate.opsForHash().values(seckillProductCacheKey);
        ArrayList<SeckillProductVo> list = new ArrayList<>();
        for (Object o : values) {

            list.add(JSON.parseObject((String)o,SeckillProductVo.class));
        }
        return list;


    }

    @Override
    public SeckillProductVo findFromCache(Integer time, Long seckillId) {
        String realKey = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(String.valueOf(time));
       String objStr=(String) redisTemplate.opsForHash().get(realKey,String.valueOf(seckillId));
        return JSON.parseObject(objStr,SeckillProductVo.class);
    }


}
